package nl.tue.be.ds.duraark.bSDD.ontology;

import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.codehaus.jackson.JsonNode;

import com.hp.hpl.jena.ontology.AnnotationProperty;
import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.XSD;

public class PropertyProcessor {

	private OntModel ontModel;
	private OntClass ontoClass;
	private String ns0;

	public PropertyProcessor(OntModel ontModel, OntClass ontoClass, String ns0) {
		super();
		this.ontModel = ontModel;
		this.ontoClass = ontoClass;
		this.ns0 = ns0;
	}

	public void textValueSubNodeProcess(Entry<String, JsonNode> subNode) {

		String key = subNode.getKey();
		AnnotationProperty annotationProperty = ontModel
				.createAnnotationProperty(ns0 + key);
		ontoClass.addProperty(annotationProperty, subNode.getValue()
				.getTextValue());
		if (key.equals("status") || key.equals("conceptType"))
			annotationProperty.setRange(XSD.xstring);
		else if (key.equals("guid") || key.equals("versionId"))
			annotationProperty.setRange(XSD.ID);
		else if (key.equals("versionDate"))
			annotationProperty.setRange(XSD.dateTime);
	}

	public Resource objectValueSubNodeProcess(Entry<String, JsonNode> subNode) {

		JsonNode dtvalueJN = subNode.getValue();
		Iterator<Entry<String, JsonNode>> iter = dtvalueJN.getFields();
		Resource r = ontModel.createResource();

		while (iter.hasNext()) {

			Entry<String, JsonNode> ssubNode = iter.next();

			if (ssubNode.getValue().isTextual()) {
				Property property = ontModel.createProperty(ns0
						+ ssubNode.getKey());
				r.addProperty(property, ssubNode.getValue().getTextValue());
				// ontoClass.addProperty(property,
				// ssubNode.getValue().getTextValue());

			} else if (ssubNode.getValue().isObject()) {
				Resource re = objectValueSubNodeProcess(ssubNode);
				Property property = ontModel.createProperty(ns0
						+ ssubNode.getKey());
				r.addProperty(property, re);
			}

		}

		return r;
	}

	public void arrayValueSubNodeProcess(Entry<String, JsonNode> subNode) {

		JsonNode dtvalueJN = subNode.getValue();

		Iterator<JsonNode> iter = dtvalueJN.iterator();
		while (iter.hasNext()) {
			JsonNode ssubNode = iter.next();
			if (ssubNode.isObject()) {
				Map.Entry<String, JsonNode> newsinSubNode = new AbstractMap.SimpleEntry<String, JsonNode>(
						subNode.getKey(), ssubNode);
				String key = newsinSubNode.getKey();
				DatatypeProperty datatypeProperty = ontModel
						.createDatatypeProperty(ns0 + key);
				Resource r = objectValueSubNodeProcess(newsinSubNode);
				ontoClass.addProperty(datatypeProperty, r);
			}
		}

	}

	public void objectPropertyProcess(
			Entry<String, String> conInRelGuidRelTypePair) {
		OntClass domainClass;

		switch (conInRelGuidRelTypePair.getValue()) {

		case "ASSOCIATES":
			ObjectProperty associates = ontModel.createObjectProperty(ns0
					+ "ASSOCIATES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(associates, ontoClass);
			associates.addDomain(domainClass);
			associates.addRange(ontoClass);
			break;

		case "ASSIGNS_COLLECTIONS":
			ObjectProperty acs = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_COLLECTIONS");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(acs, ontoClass);
			acs.addDomain(domainClass);
			acs.addRange(ontoClass);
			break;

		case "ASSIGNS_MEASURES":
			ObjectProperty ams = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_MEASURES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(ams, ontoClass);
			ams.addDomain(domainClass);
			ams.addRange(ontoClass);
			break;

		case "ASSIGNS_PROPERTIES":
			ObjectProperty aps = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_PROPERTIES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(aps, ontoClass);
			aps.addDomain(domainClass);
			aps.addRange(ontoClass);
			break;

		case "ASSIGNS_UNITS":
			ObjectProperty aus = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_UNITS");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(aus, ontoClass);
			aus.addDomain(domainClass);
			aus.addRange(ontoClass);
			break;

		case "ASSIGNS_VALUES":
			ObjectProperty avs = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_VALUES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(avs, ontoClass);
			avs.addDomain(domainClass);
			avs.addRange(ontoClass);
			break;

		case "ASSIGNS_PROPERTY_WITH_VALUES":
			ObjectProperty apvs = ontModel.createObjectProperty(ns0
					+ "ASSIGNS_PROPERTY_WITH_VALUES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(apvs, ontoClass);
			apvs.addDomain(domainClass);
			apvs.addRange(ontoClass);
			break;

		case "CLASSIFIES":
			ObjectProperty classifies = ontModel.createObjectProperty(ns0
					+ "CLASSIFIES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(classifies, ontoClass);
			classifies.addDomain(domainClass);
			classifies.addRange(ontoClass);
			break;

		case "COLLECTS":
			ObjectProperty collects = ontModel.createObjectProperty(ns0
					+ "COLLECTS");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(collects, ontoClass);
			collects.addDomain(domainClass);
			collects.addRange(ontoClass);
			break;

		case "COMPOSES":
			ObjectProperty composes = ontModel.createObjectProperty(ns0
					+ "COMPOSES");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(composes, ontoClass);
			composes.addDomain(domainClass);
			composes.addRange(ontoClass);
			break;

		case "DOCUMENTS":
			ObjectProperty documents = ontModel.createObjectProperty(ns0
					+ "DOCUMENTS");
			domainClass = ontModel.createClass(OntoGenerator.ontoNamespace
					+ conInRelGuidRelTypePair.getKey());
			domainClass.addProperty(documents, ontoClass);
			documents.addDomain(domainClass);
			documents.addRange(ontoClass);
			break;

		}

	}

}
